package ml.stayfool;

import ml.stayfool.configuration.ConfigProps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicInteger;

public class App {

    private static final Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) throws Exception {
        App app = new App();

        ListFileVisitor visitor = new ListFileVisitor(app.fileMap, app.failureFileSet);

        for (String path : ConfigProps.imgdirs()) {
            Files.walkFileTree(Paths.get(path), visitor);
        }

        app.moveFile();

        app.statistics();
    }

    private ConcurrentMap<String, ConcurrentSkipListSet<Path>> fileMap = new ConcurrentHashMap<>();
    private ConcurrentSkipListSet<Path> failureFileSet = new ConcurrentSkipListSet<>();

    private void moveFile() {
        fileMap.keySet().parallelStream().forEach(newName -> {
            try {
                Path dir = Paths.get(newName).getParent();
                if (!Files.exists(dir))
                    Files.createDirectories(dir);
            } catch (IOException e) {
                logger.error("create dir failed", e);
            }

            AtomicInteger no = new AtomicInteger(0);

            fileMap.get(newName).forEach(path -> {
                String tmpName = newName.substring(0, newName.lastIndexOf(".")) +
                        "-" +
                        no.getAndIncrement() +
                        newName.substring(newName.lastIndexOf("."));

                Path target = Paths.get(tmpName);
                try {
                    Files.move(path, target);
                    logger.info("move file from {} to {} successed", path, target);
                } catch (IOException e) {
                    failureFileSet.add(path);
                    logger.error("move file from {} to {} failed, {}", path, target, e);
                }
            });

        });
    }

    private void statistics() throws Exception {

        AtomicInteger desCount = new AtomicInteger();

        Files.walkFileTree(Paths.get(ConfigProps.outdir()), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                desCount.incrementAndGet();
                return FileVisitResult.CONTINUE;
            }
        });

        int srcCount = fileMap.values().stream().map(s -> s.size()).reduce((a, b) -> a + b).get();

        logger.info("sourece : {}, successed : {}, failed: {}",
                srcCount,
                desCount.get(),
                failureFileSet.size());
        failureFileSet.forEach(p -> logger.info("{}", p));
    }

}
